package com.dbflow5.query;

import com.dbflow5.annotation.ConflictAction;
import com.dbflow5.config.FlowManager;
import com.dbflow5.sql.Query;
import com.dbflow5.sql.QueryCloneable;

/**
 * Description: The SQLite UPDATE query. Will update rows in the DB.
 */
public class Update<T> implements Query, QueryCloneable<Update<T>> {

    /**
     * The conflict action to resolve updates.
     */
    private ConflictAction conflictAction = ConflictAction.NONE;

    private final Class<T> table;

    public Update(Class<T> table) {
        this.table = table;
    }

    @Override
    public String getQuery() {
        StringBuilder queryBuilder = new StringBuilder("UPDATE ");
        if (conflictAction != ConflictAction.NONE) {
            queryBuilder.append("OR").append(" ").append(conflictAction.name()).append(" ");
        }
        queryBuilder.append(FlowManager.getTableName(table)).append(" ");
        return queryBuilder.toString();
    }

    @Override
    public Update<T> cloneSelf() {
        return new Update<>(table)
                .conflictAction(conflictAction);
    }

    public Update<T> conflictAction(ConflictAction conflictAction) {
        this.conflictAction = conflictAction;
        return this;
    }

    public Update<T> or(ConflictAction conflictAction) {
        return conflictAction(conflictAction);
    }

    /**
     * UPDATE query
     * @return This instance.
     */
    public Update<T> orRollback() {
        return conflictAction(ConflictAction.ROLLBACK);
    }

    /**
     * UPDATE query
     * @return This instance.
     */
    public Update<T> orAbort() {
        return conflictAction(ConflictAction.ABORT);
    }

    /**
     * UPDATE query
     * @return This instance.
     */
    public Update<T> orReplace() {
        return conflictAction(ConflictAction.REPLACE);
    }

    /**
     * UPDATE query
     * @return This instance.
     */
    public Update<T> orFail() {
        return conflictAction(ConflictAction.FAIL);
    }

    /**
     * UPDATE query
     * @return This instance.
     */
    public Update<T> orIgnore() {
        return conflictAction(ConflictAction.IGNORE);
    }

    /**
     * Begins a SET piece of the SQL query
     *
     * @param conditions The array of conditions that define this SET statement
     * @return A SET query piece of this statement
     */
    public Set<T> set(SQLOperator... conditions) {
        return new Set<>(this, table)
                .conditions(conditions);
    }
}

